import json
import datetime
import time
import random
import hashlib
import requests

from json import JSONDecodeError
from urllib.parse import urlencode

# 用户填写部分
###################################
configData = {
    'GAME_UID': '', #原神游戏UID
    'BBS_UID': '', # 米游社UID
    'BBS_COOKIE': '', # 米游社Cookie
    'SERVERCHAN_KEY': '', # Server酱SendKey
    'MODE_reminder_reporter': 'reminder' # 程序提醒模式或报告模式配置
}
resinThreshold = 120 # 树脂提醒阈值 
###################################

class ServerChanHandler(object):
    def __init__(self, configData):
        # server酱key
        self.m_key = configData['SERVERCHAN_KEY']

    def sendMessage(self, message: str):
        urlmessage = urlencode({'text': message})
        url = 'https://sc.ftqq.com/' + self.m_key + '.send?' + urlmessage
        requests.get(url)

class DailyNoteHandler(object):
    def __init__(self, configData):
        # 与米游社有关的校验码
        self.m_salt = 'xV8v4Qu54lUKrEYFZkJhB8cuOh9Asafs'
        
        # 发送请求所需的参数
        self.m_gameUID = {
            'role_id': configData['GAME_UID'],
            'server': 'cn_gf01'
        }
        self.m_bbsData = {
            'account_id': configData['BBS_UID'],
            'cookie_token': configData['BBS_COOKIE']
        }

        self.m_DailyNote = {}
        self.m_refreshSucceed = False
        

# public

    def getDailyNote(self):
        if self.m_refreshSucceed == True:
            return self.m_DailyNote
        else:
            return None

    def refreshDailyNote(self):
        self.m_refreshSucceed = False

        ds = self.getDS(self.m_salt, self.m_gameUID)

        session = requests.Session()
        session.trust_env = False

        session.headers = {
            'x-rpc-client_type': '5',
            'x-rpc-app_version': '2.28.1',
            'Host': 'api-takumi-record.mihoyo.com',
            'DS': ds,
        }
        url = 'https://api-takumi.mihoyo.com/game_record/app/genshin/api/dailyNote'
        response = session.get(url, params=self.m_gameUID, cookies=self.m_bbsData)

        # Handle Error 
        try:
            response = response.json()
        except JSONDecodeError:
            print('ERROR: JSONDecodeError, response.text: ' + response.text)
            return False

        if response['message'] != 'OK':
            print('ERROR: message not OK: ' + response['message'])
            return False

        # 处理HTTP返回结果
        
        if response['retcode'] != 0:
            if response['retcode'] == 10001:
                print('ERROR: Cookie错误/过期，请重置Cookie')
                return False
            print('ERROR: Api报错，返回内容为：\r\n'+ str(response) + '\r\n出现这种情况可能是UID输入错误 or 不存在')
            return False
        else:
            pass

        self.m_DailyNote = response['data']

        # 剩余探索派遣计算
        max_expedition_num = self.m_DailyNote['max_expedition_num']
        current_expedition_list = self.m_DailyNote['expeditions']
        ongoing_expedition_num = 0
        for expedition in current_expedition_list:
            if str(expedition['status']) != 'Finished':
                ongoing_expedition_num += 1

        self.m_DailyNote['remain_expedition_num'] = max_expedition_num - ongoing_expedition_num

        self.m_refreshSucceed = True
        return True

# private

    def getDS(self, salt: str, gameUID: str): # get dynamic secrets
        t = int(time.time())
        r = random.randint(100000, 200000)
        q = urlencode(gameUID)
        text = f'salt={salt}&t={t}&r={r}&b=&q={q}'
        # get md5
        c = self.getMd5(text)
        DS = f'{t},{r},{c}'
        return DS

    def getMd5(self, text):
        md5 = hashlib.md5()
        md5.update(text.encode())
        md5Code = md5.hexdigest()
        return md5Code

def handler(event, context):
    MyDailyNoteHandler = DailyNoteHandler(configData)

    if MyDailyNoteHandler.refreshDailyNote():
        DailyNote = MyDailyNoteHandler.getDailyNote()
    else:
        # get DailyNote Failed
        return 'Error'
    
    ServerChan = ServerChanHandler(configData)

    # 树脂、每日任务、探索派遣、周本

    # 树脂
    current_resin = DailyNote['current_resin']
    max_resin = DailyNote['max_resin']
    resin_recovery_time = DailyNote['resin_recovery_time']
    resin_recovery_time_hours = str(datetime.timedelta(seconds=int(resin_recovery_time)))
    expected_resin_recovery_time = str(datetime.datetime.now() + datetime.timedelta(seconds=int(resin_recovery_time)) + datetime.timedelta(hours=int(8)))

    # 每日任务
    finished_task_num = DailyNote['finished_task_num']
    total_task_num = DailyNote['total_task_num']
    remain_task_num = total_task_num - finished_task_num

    # 探索派遣
    current_expedition_num = DailyNote['current_expedition_num']
    max_expedition_num = DailyNote['max_expedition_num']
    remain_expedition_num = DailyNote['remain_expedition_num']

    # 周本
    remain_resin_discount_num = DailyNote['remain_resin_discount_num']
    resin_discount_num_limit = DailyNote['resin_discount_num_limit']

    if configData['MODE_reminder_reporter'] == 'reporter':
        resin_str = f'剩余树脂:{current_resin}/{max_resin}, ' + f'恢复时间:{resin_recovery_time_hours}, ' + f'回满时刻:{expected_resin_recovery_time}, '

        task_str = f'剩余每日:{remain_task_num}/{total_task_num}, '

        expedition_str = f'剩余派遣:{remain_expedition_num}/{max_expedition_num}, '

        discount_str = f'剩余周本:{remain_resin_discount_num}/{resin_discount_num_limit}'

        MessageToSend = resin_str + task_str + expedition_str + discount_str
        ServerChan.sendMessage(MessageToSend)
        print(MessageToSend)

    elif configData['MODE_reminder_reporter'] == 'reminder':
        str_flag = False
        resin_str = ''
        task_str = ''
        expedition_str = ''
        discount_str = ''

        if current_resin > resinThreshold :
            resin_str = f'剩余树脂:{current_resin}/{max_resin}, ' + f'恢复时间:{resin_recovery_time_hours}, ' + f'回满时刻:{expected_resin_recovery_time}, '
            str_flag = True

        if remain_task_num > 0:
            task_str = f'剩余每日:{remain_task_num}/{total_task_num}, '
            str_flag = True

        if remain_expedition_num > 0:
            expedition_str = f'剩余派遣:{remain_expedition_num}/{max_expedition_num}, '
            str_flag = True

        if remain_resin_discount_num > 0:
            discount_str = f'剩余周本:{remain_resin_discount_num}/{resin_discount_num_limit}'
            str_flag = True
        
        if str_flag:
            MessageToSend = resin_str + task_str + expedition_str + discount_str
            ServerChan.sendMessage(MessageToSend)
            print(MessageToSend)
        else:
            print('There is nothing to be reminded.')

    return 'Done'
     